using System;
using System.Collections.Generic;
using System.Text;

using System.Data;
using System.IO;
using System.CodeDom.Compiler;
using System.CodeDom;
using Microsoft.CSharp;
using System.Data.SqlClient;
using System.Reflection;
using ESBSimpleSamples.ServiceClient.Generator.WSDL;

namespace ESBSimpleSamples.ServiceClient.Generator.Scripts
{
    /// <summary>
    /// Generates a typed ServiceRequest class for a SOAP method
    /// </summary>
    public class ServiceRequestScript : CodeDomScript
    {

        protected override void AddConstructor()
        {
            CodeConstructor constructor = new CodeConstructor();
            constructor.Attributes = MemberAttributes.Public;
            this.AddMember(constructor);
        }

        protected override void AddLocalFields()
        {
            //do nothing
        }

        protected override void AddProperties()
        {
            //do nothing
        }

        protected override void AddMethods()
        {
            this.AddPrepareRequestMethod();
        }

        /// <summary>
        /// Generated from CodeDomAssistant
        /// </summary>
        private void AddPrepareRequestMethod()
        {
            //
            // Function PrepareRequest()
            //
            CodeMemberMethod _PrepareRequest_method1 = new CodeMemberMethod();
            _PrepareRequest_method1.Attributes = MemberAttributes.Override | MemberAttributes.FamilyAndAssembly | MemberAttributes.FamilyOrAssembly | MemberAttributes.Public;
            _PrepareRequest_method1.Name = "PrepareRequest";
            CodeVariableDeclarationStatement _decl1 = new CodeVariableDeclarationStatement();
            CodeObjectCreateExpression _new1 = new CodeObjectCreateExpression();
            CodeTypeReference _ItineraryBuilder_type1 = new CodeTypeReference("ItineraryBuilder");
            _new1.CreateType = _ItineraryBuilder_type1;
            _decl1.InitExpression = _new1;
            _decl1.Name = "builder";
            CodeTypeReference _ItineraryBuilder_type2 = new CodeTypeReference("ItineraryBuilder");
            _decl1.Type = _ItineraryBuilder_type2;
            _PrepareRequest_method1.Statements.Add(_decl1);

            CodeExpressionStatement _expr1 = new CodeExpressionStatement();
            CodeMethodInvokeExpression _invoke1 = new CodeMethodInvokeExpression();
            CodePrimitiveExpression _value1 = new CodePrimitiveExpression();
            _value1.Value = this.ServiceProviderName;
            _invoke1.Parameters.Add(_value1);

            CodePrimitiveExpression _value2 = new CodePrimitiveExpression();
            _value2.Value = this._method.Name;
            _invoke1.Parameters.Add(_value2);

            CodeMethodReferenceExpression _AddRoutingService_method1 = new CodeMethodReferenceExpression();
            _AddRoutingService_method1.MethodName = "AddRoutingService";
            CodeVariableReferenceExpression _arg1 = new CodeVariableReferenceExpression();
            _arg1.VariableName = "builder";
            _AddRoutingService_method1.TargetObject = _arg1;
            _invoke1.Method = _AddRoutingService_method1;
            _expr1.Expression = _invoke1;
            _PrepareRequest_method1.Statements.Add(_expr1);

            CodeExpressionStatement _expr2 = new CodeExpressionStatement();
            CodeMethodInvokeExpression _invoke2 = new CodeMethodInvokeExpression();
            CodeMethodReferenceExpression _AddRequestResponseService_method1 = new CodeMethodReferenceExpression();
            _AddRequestResponseService_method1.MethodName = "AddRequestResponseService";
            CodeVariableReferenceExpression _arg2 = new CodeVariableReferenceExpression();
            _arg2.VariableName = "builder";
            _AddRequestResponseService_method1.TargetObject = _arg2;
            _invoke2.Method = _AddRequestResponseService_method1;
            _expr2.Expression = _invoke2;
            _PrepareRequest_method1.Statements.Add(_expr2);

            CodeVariableDeclarationStatement _decl2 = new CodeVariableDeclarationStatement();
            CodeObjectCreateExpression _new2 = new CodeObjectCreateExpression();
            CodeTypeReference _ItineraryRequest_type1 = new CodeTypeReference("ItineraryRequest");
            _new2.CreateType = _ItineraryRequest_type1;
            _decl2.InitExpression = _new2;
            _decl2.Name = "request";
            CodeTypeReference _ItineraryRequest_type2 = new CodeTypeReference("ItineraryRequest");
            _decl2.Type = _ItineraryRequest_type2;
            _PrepareRequest_method1.Statements.Add(_decl2);

            CodeAssignStatement _assign1 = new CodeAssignStatement();
            CodePropertyReferenceExpression _prop1 = new CodePropertyReferenceExpression();
            _prop1.PropertyName = "Header";
            CodeVariableReferenceExpression _arg3 = new CodeVariableReferenceExpression();
            _arg3.VariableName = "request";
            _prop1.TargetObject = _arg3;
            _assign1.Left = _prop1;
            CodeMethodInvokeExpression _invoke3 = new CodeMethodInvokeExpression();
            CodeMethodReferenceExpression _GetItinerary_method1 = new CodeMethodReferenceExpression();
            _GetItinerary_method1.MethodName = "GetItinerary";
            CodeVariableReferenceExpression _arg4 = new CodeVariableReferenceExpression();
            _arg4.VariableName = "builder";
            _GetItinerary_method1.TargetObject = _arg4;
            _invoke3.Method = _GetItinerary_method1;
            _assign1.Right = _invoke3;
            _PrepareRequest_method1.Statements.Add(_assign1);

            CodeAssignStatement _assign2 = new CodeAssignStatement();
            CodePropertyReferenceExpression _prop2 = new CodePropertyReferenceExpression();
            _prop2.PropertyName = "Body";
            CodeVariableReferenceExpression _arg5 = new CodeVariableReferenceExpression();
            _arg5.VariableName = "request";
            _prop2.TargetObject = _arg5;
            _assign2.Left = _prop2;
            CodeMethodInvokeExpression _invoke4 = new CodeMethodInvokeExpression();
            CodeMethodReferenceExpression _GetRequestBody_method1 = new CodeMethodReferenceExpression();
            _GetRequestBody_method1.MethodName = "GetRequestBody";
            CodeThisReferenceExpression _this1 = new CodeThisReferenceExpression();
            _GetRequestBody_method1.TargetObject = _this1;
            _invoke4.Method = _GetRequestBody_method1;
            _assign2.Right = _invoke4;
            _PrepareRequest_method1.Statements.Add(_assign2);

            CodeMethodReturnStatement _return1 = new CodeMethodReturnStatement();
            CodeVariableReferenceExpression _arg6 = new CodeVariableReferenceExpression();
            _arg6.VariableName = "request";
            _return1.Expression = _arg6;
            _PrepareRequest_method1.Statements.Add(_return1);
            this.AddMember(_PrepareRequest_method1);
        }

        protected override void AddStructs()
        {
            //do nothing
        }

        private string ServiceProviderName
        {
            get
            {
                string parameterValue = this.GetParameterValue("serviceProviderName");
                if (string.IsNullOrEmpty(parameterValue))
                {
                    string[] namespaceParts = this.Namespace.Split('.');
                    parameterValue = namespaceParts[0];
                    this.ServiceProviderName = parameterValue;
                }
                return parameterValue;
            }
            set { this.SetParameterValue("serviceProviderName", value); }
        }

        protected override string Namespace
        {
            get
            {
                string parameterValue = base.Namespace;
                if (string.IsNullOrEmpty(parameterValue))
                {
                    string[] namespaceParts = this._metadata.TargetNamespace.Replace(@"//", @"/").Split('/');
                    parameterValue = namespaceParts[1];
                    this.Namespace = parameterValue;
                }
                return parameterValue;
            }
            set
            {
                base.Namespace = value;
            }
        }

        protected override void Process()
        {
            this.ClassName = this._method.Name;
            this.OutputClass();
        }

        public override string Name
        {
            get { return "Service Request"; }
        }

        protected override void SetupDeclaration()
        {
            base.SetupDeclaration();
            this.AddImport("ESBSimpleSamples.ServiceClient.Itineraries");
            this.AddImport("ESBSimpleSamples.ServiceClient.ServiceRequests");
            CodeTypeReference baseClass = new CodeTypeReference("ESBServiceRequest");
            baseClass.TypeArguments.Add(new CodeTypeReference(string.Format("{0}Request", this._method.RequestTypeName)));
            baseClass.TypeArguments.Add(new CodeTypeReference(this._method.ResponseTypeName));
            this.Declaration.BaseTypes.Add(baseClass);
        }
    }
}